package com.rimi.config;

import com.rimi.shiro.AnyRolesAuthorizationFilter;
import com.rimi.shiro.BearerFilter;
import com.rimi.shiro.BearerRealm;
import com.rimi.shiro.MysqlRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.mgt.SubjectDAO;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liHaiYang
 * @version V1.0
 * @Description: (用一句话描述该文件做什么)
 * @date 2021/6/30 14:41
 */
@Configuration
public class ShiroConfig {

    @Autowired(required = false)
    SubjectDAO subjectDAO;

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(){
        //创建过滤器工厂
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        //登录界面的地址
        filterFactoryBean.setLoginUrl("/login");

        //成功界面的地址
        //filterFactoryBean.setSuccessUrl(this.successUrl);

        //权限校验失败的跳转地址
//        filterFactoryBean.setUnauthorizedUrl("/401.html");

        //使用哪一种安全管理器
        filterFactoryBean.setSecurityManager(securityManager());
        //使用的全局过滤器集合
        //filterFactoryBean.setGlobalFilters(this.globalFilters());

        //创建过滤规则（有先后顺序）,从上到下进行匹配，以第一个匹配到的规则为准
//        Map<String,String> define = new LinkedHashMap<>();
//
//        // /user/**格式的url必须经过身份校验
//        define.put("/user/**","authc");
//        //所有的url都不进行校验
//        define.put("/**","anon");
//        //使用的自动义过滤规则
//        filterFactoryBean.setFilterChainDefinitionMap(define);

        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.append("/user/**=authcBearer");
        stringBuilder.append("\n");
        stringBuilder.append("/pets/**=authcBearer");
        stringBuilder.append("\n");
        stringBuilder.append("/news/**=authcBearer");
        stringBuilder.append("\n");
//        stringBuilder.append("/user/**=authc");
//        stringBuilder.append("\n");
        stringBuilder.append("/**=anon");



        stringBuilder.append("\n");
        filterFactoryBean.setFilterChainDefinitions(stringBuilder.toString());


        //自定义的shiro内置过滤器
        //filterFactoryBean.setFilters(this.filterMap);
        Map<String, Filter> filterMap = new HashMap<>();
        //给过滤器取一个名字，交给shrio管理
        filterMap.put("roles",new AnyRolesAuthorizationFilter());
        filterMap.put("authcBearer",new BearerFilter());
        filterFactoryBean.setFilters(filterMap);


        return filterFactoryBean;
    }

    @Bean
    public SessionsSecurityManager securityManager() {

        //创建安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        //设置身份认证和权限校验的认证校验方式

        List<Realm> mysqlRealms = Arrays.asList(mysqlRealm(), bearerRealm());
        securityManager.setRealms(mysqlRealms);

        //关闭session存储
        DefaultSubjectDAO defaultSubjectDAO = (DefaultSubjectDAO)subjectDAO;
        DefaultSessionStorageEvaluator sessionStorageEvaluator = (DefaultSessionStorageEvaluator) defaultSubjectDAO.getSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        securityManager.setSubjectDAO(subjectDAO);

        return securityManager;


    }

    @Bean
    public MysqlRealm mysqlRealm(){
        MysqlRealm mysqlRealm = new MysqlRealm();
        //设置密码比较器
        mysqlRealm.setCredentialsMatcher(credentialsMatcher());
        return mysqlRealm;
    }

    @Bean
    public BearerRealm bearerRealm(){
        BearerRealm bearerRealm = new BearerRealm();
        return bearerRealm;
    }
    public HashedCredentialsMatcher credentialsMatcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //采用哪种hash算法进行解密
        matcher.setHashAlgorithmName("md5");

        //加密次数
        matcher.setHashIterations(10);
        return matcher;
    }
}
